package com.gitee.huanminabc.db_freedom.proxy;


import com.gitee.huanminabc.db_freedom.config.MybatisFreedomConfig;
import com.gitee.huanminabc.db_freedom.wrapper.AbstractBaseWrapper;
import com.gitee.huanminabc.db_freedom.wrapper.AbstractSqlWrapper;
import com.gitee.huanminabc.db_freedom.wrapper.SqlWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Slf4j
public class ProxyCglibFactory implements MethodInterceptor {
    private final Object target;
    private final ActionProxy actionProxy;

    public ProxyCglibFactory(ActionProxy actionProxy, Object target) {
        this.actionProxy = actionProxy;
        this.target = target;
    }


    /**
     * @param proxy  代理的对象也就是ServiceProxy他自己
     * @param method 被代理的方法
     * @param args   被代理的方法传入的参数
     * @return 返回被代理方法的执行的结果
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        //代理对象,对方法进行增强
        if (actionProxy != null && target != null&&shouldProxyReturnObject(method)) {
            //前置增强
            actionProxy.before(target, method, args);
            Object invoke = null;
            try {
                invoke = method.invoke(target, args);
            } catch (Throwable e) {
                //一般来说最内部的异常先打印, 然后在打印外部的异常
                if (target instanceof AbstractSqlWrapper) {
                    log.error("异常链路:{}", ((AbstractSqlWrapper<?, ?>) target).getOperationRecord());
                }
                throw e;
            }
            //后置增强,可以改变返回值
            invoke=actionProxy.after(target, method, args, invoke);
            if (shouldProxyReturnObject(invoke)) {
                return createProxyForReturnObject(invoke);
            }
            return invoke;
        }
        return method.invoke(target, args);

    }

    //前置判断
    private boolean shouldProxyReturnObject( Method method) {
        //Object的方法不代理
        if (method.getDeclaringClass().equals(Object.class)) {
            return false;
        }
        //跳过AbstractSqlWrapper的方法
        if (method.getDeclaringClass().equals(AbstractSqlWrapper.class)) {
            return false;
        }
        //跳过AbstractBaseWrapper的方法
        if (method.getDeclaringClass().equals(AbstractBaseWrapper.class)) {
            return false;
        }
        //跳过SqlWrapper的方法
        if (method.getDeclaringClass().equals(SqlWrapper.class)) {
            return false;
        }

        return true;
    }

    private boolean shouldProxyReturnObject(Object result) {
        // 这里添加判断逻辑，例如，可以根据对象的类型或其他条件来判断是否需要代理
        // 假设我们只对某个特定接口的实现类进行代理
        return result instanceof SqlWrapper;
    }

    //因为是链路调用,所以需要对返回值进行代理,否则就丢失代理了
    private Object createProxyForReturnObject(Object result) {
        //如果是代理对象那么就跳过
        if (result instanceof Proxy) {
            return result;
        }

        // 这里创建代理对象，具体实现取决于你的代理机制，例如使用JDK动态代理或CGLIB等
        // 以下是一个使用JDK动态代理的示例
        if (result instanceof AbstractSqlWrapper) {
            ProxyCglibFactory proxyCglibFactory = new ProxyCglibFactory(MybatisFreedomConfig.actionProxy, result);
            return ProxyCglibInstance.getObject(result, proxyCglibFactory);
        }
        // 如果不需要代理，或者无法代理，则直接返回原对象
        return result;
    }
}
